import { ICanPickupMoneyElement } from "../configs/CanPickupMoney"
import { GameConfig } from "../configs/GameConfig"
import { Attribute } from "../etc/Attribute"
import { updater } from "../etc/Updater"
import { LevelModuleC, LevelModuleData, LevelModuleS } from "./LevelModule"
import { PlayerModuleS } from "./PlayerModule"

class PickupMoneyMapping {
    private static emptyArray = []
    private static mapping: Map<number, ICanPickupMoneyElement[]>

    static getPickupMoneyIDArrayByKind(kind: number):ICanPickupMoneyElement[] {
        this.mappingChecker()
        // 这个关卡没有金币
        if(!this.mapping.has(kind)) return this.emptyArray
        return this.mapping.get(kind)
    }

    private static mappingChecker() {
        if (this.mapping) return
        this.mapping = new Map()
        for (const cfg of GameConfig.CanPickupMoney.getAllElement()) {
            if (!this.mapping.has(cfg.Kind)) this.mapping.set(cfg.Kind, [])
            this.mapping.get(cfg.Kind).push(cfg)
        }
    }
}

export class PickupMoneyModuleData extends Subdata{
    @Decorator.persistence()
    pickupMoneyArray:string[]

    protected initDefaultData(): void {
        this.pickupMoneyArray = []
    }
}

class PickupMoney{
    moneyGameObject:GameObject | undefined
    gameObjectGUID:string
    redPackUI:GameObject

    constructor(obj:GameObject) {
        this.moneyGameObject = obj
        this.gameObjectGUID = obj.assetId
        this.redPackUI = this.moneyGameObject.getChildByName('世界UI')
    }

    // 未激活
    isDisabled():boolean {
        return this.moneyGameObject.getVisibility() == false
    }

    disable(){
        if(!this.moneyGameObject) return
        this.moneyGameObject.setVisibility(false, true)
    }

    enable(){
        if(!this.moneyGameObject) return
        this.moneyGameObject.setVisibility(true, true)
    }
}

export class PickupMoneyModuleC extends ModuleC<PickupMoneyModuleS, PickupMoneyModuleData>{
    private pickupMoneyArray:PickupMoney[] = []

    protected onStart(): void {
        let moneyArray = GameObject.findGameObjectsByTag('money')
        for (const money of moneyArray) {
            let pickup = new PickupMoney(money)
            this.pickupMoneyArray.push(pickup)
        }
        this.refillCurrentLevelPickupMoney()
    }

    protected onUpdate(dt: number): void { 
        let dir = Vector.multiply(Camera.currentCamera.worldTransform.getForwardVector(), -1)
        let rot = dir.toRotation()
        for (const pickup of this.pickupMoneyArray) {
            // 朝向摄像机
            pickup.redPackUI.worldTransform.rotation = rot
        }
    }

    // 拾取检查
    @updater.updateByFrameInterval(15)
    private pickupRecentMoneyChecker(){
        let playerPosition = this.localPlayer.character.worldTransform.position
        for (const pickupMoney of this.pickupMoneyArray) {
            // 未激活
            if(pickupMoney.isDisabled()) continue
            // 距离判定
            let distance = Vector.distance(playerPosition, pickupMoney.moneyGameObject.worldTransform.position)
            if(distance > 250) continue
            // 播放拾取特效 
            EffectService.playAtPosition('151532', pickupMoney.moneyGameObject.worldTransform.position, {
                scale: new Vector(3,3,3),
                rotation: Player.localPlayer.character.worldTransform.rotation
            })
            // 拾取这个金币
            pickupMoney.disable()
            this.server.net_pickup_money(pickupMoney.gameObjectGUID)
            // 播放金币音效
            SoundService.playSound('136208')
        }
    }

    private refillCurrentLevelPickupMoney(){
        for (const pickupMoney of this.pickupMoneyArray) {
            if(this.data.pickupMoneyArray.includes(pickupMoney.gameObjectGUID)) {
                pickupMoney.disable()
            }else{
                pickupMoney.enable()
            }
        }
    }
}

export class PickupMoneyModuleS extends ModuleS<PickupMoneyModuleC, PickupMoneyModuleData>{

    protected onStart(): void {
        ModuleService.getModule(LevelModuleS).onPlayerLevelChangeEvent.add(this.onPlayerLevelChanged, this)
    }

    net_pickup_money(moneyGUID:string){
        if(this.currentData.pickupMoneyArray.includes(moneyGUID)) return

        this.currentData.pickupMoneyArray.push(moneyGUID)

        let playerMD = ModuleService.getModule(PlayerModuleS)
        playerMD.addPlayerAttr(this.currentPlayerId, Attribute.EnumAttributeType.money, 1)

        console.warn(`玩家拾取金币, 当前关卡拾取总数:${this.currentData.pickupMoneyArray.length}`);
        
        this.currentData.save(true)
    }

    onPlayerLevelChanged(playerID:number){
        // 清空这一关玩家已领取的金币
        let data = this.getPlayerData(playerID)
        data.pickupMoneyArray = []
        data.save(true)
    }
}